package com.wyw.hemerocallis.service.hystrix;

import com.netflix.hystrix.*;
import com.wyw.hemerocallis.service.NacosClientService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.client.ServiceInstance;

import java.util.Collections;
import java.util.List;

import static com.netflix.hystrix.HystrixCommandProperties.ExecutionIsolationStrategy.THREAD;


/**
 * NacosClientService实现包装
 * Hystrix舱壁模式
 *  1、线程池
 *  2、信号量: 算法+数据结构，有限状态机（可以理解成通过status表示当前处于的状态）
 *
 * @author Mr Wu    yewen.wu.china@gmail.com
 * <p>
 * Update History:
 * Author        Time            Content
 */
@Slf4j
public class NacosClientHystrixCommand extends HystrixCommand<List<ServiceInstance>> {
    /** 需要保护的服务 */
    private final NacosClientService nacosClientService;

    /** 方法需要传递的参数 */
    private final String serviceId;

    public NacosClientHystrixCommand(NacosClientService nacosClientService, String serviceId) {
        //线程隔离
        super(
            Setter.withGroupKey(
                    //对HystrixCommand进行分组，主要是便于统计与监控
                    HystrixCommandGroupKey.Factory.asKey("NacosClientService"))
                    //标识唯一的熔断器
                .andCommandKey(HystrixCommandKey.Factory.asKey("NacosClientHystrixCommand"))
                .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("NacosClientPool"))
                //线程池key配置
                .andCommandPropertiesDefaults(
                        HystrixCommandProperties.Setter()
                        .withExecutionIsolationStrategy(THREAD)//线程池隔离策略
                        .withFallbackEnabled(true)//开启降级
                        .withCircuitBreakerEnabled(true)//开启熔断器
                )
        );

        // 可以配置信号量隔离策略
//        Setter semaphore =
//                Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("NacosClientService"))
//                .andCommandKey(HystrixCommandKey.Factory.asKey("NacosClientHystrixCommand"))
//                .andCommandPropertiesDefaults(
//                        HystrixCommandProperties.Setter()
//                        .withCircuitBreakerRequestVolumeThreshold(10)//至少10个请求才可以开启熔断
//                        .withCircuitBreakerSleepWindowInMilliseconds(5000)
//                        .withCircuitBreakerErrorThresholdPercentage(50)//错误率达到50%，开启熔断保护
//                        .withExecutionIsolationStrategy(SEMAPHORE)  // 指定使用信号量隔离
//                        //.....
//                );

        this.nacosClientService = nacosClientService;
        this.serviceId = serviceId;

    }

    /**
     * 把需要保护的方法调用写到run方法中
     */
    @Override
    protected List<ServiceInstance> run() throws Exception {
        log.info("NacosClientService In Hystrix Command to Get Service Instance: {}, {}",
                this.serviceId, Thread.currentThread().getName());
        return this.nacosClientService.getNacosClientInfo(this.serviceId);
    }

    /**
     * 构造降级处理策略方法
     */
    @Override
    protected List<ServiceInstance> getFallback() {
        log.warn("NacosClientService run error: {}, {}",
                this.serviceId, Thread.currentThread().getName());
        return Collections.emptyList();
    }



}
